#load "xml-light.cma";;
#load "str.cma";;

let split_str sep str = 
  Str.split(Str.regexp_string sep) str

(*custom point type stores longitude/latitude*)
class point = 
object
  val mutable longitude = 0.0
  val mutable latitude = 0.0
  method get_longitude = longitude
  method get_latitude = latitude
  method set_longitude long = longitude <- long
  method set_latitude lat = latitude <- lat
end;;

(*global test point for storing elements as point type*)
let testPoint = new point

(*custom path type for roads*)
class path = 
object
  val mutable name = "null"
  val mutable pathType = "null"
  val mutable numberOfPoints = 0
  val mutable points = Array.make 100 testPoint
  method get_name = name
  method get_pathType = pathType
  method get_numberOfPoints = numberOfPoints
  method get_points = points
  method set_name n = name <- n
  method set_pathType p = pathType <- p
  method set_numberOfPoints n = numberOfPoints <- n
  method add_points p = points <- Array.of_list p 
end;; 

(*stores the mapObject*)
class mapObject = 
object
  val mutable name = "null"
  val mutable objectType = "null"
  val mutable speed = 0
  val point = new point
  method get_name = name
  method get_objectType = objectType
  method get_point = point
  method get_speed = speed
  method set_name n = name <- n
  method set_objectType o = objectType <- o
  method set_speed s = speed <- s
  method set_point long lat = point#set_longitude long; point#set_latitude lat
end;; 

(*custom edge object/intersection*)
class edge =
object 
  val mutable name = "null"
  val mutable weight = infinity
  val mutable path_one = "null"
  val mutable path_two = "null"
  method get_name = name
  method get_weight = weight
  method get_path_one = path_one
  method get_path_two = path_two
  method set_name n = name <- n
  method set_weight w = weight <- w
  method set_path_one p1 = path_one <- p1
  method set_path_two p2 = path_two <- p2
end;;


(*Global Variables*)
let object_num = ref 0 (*to fill the ObjectArray below*)
let object_count = ref 0 (*keeps track of how many map objecs there are *)

let edge_num = ref 0
let edge_count = ref 0

let path_num = ref 0
let path_count = ref 0

(*counts total number of paths*)
let increment_path_count n =
  path_count := !path_count+1;
  Printf.printf "path count %i\n" path_count.contents

let increment_mapObject_count n  =
  object_count := !object_count+1;
  Printf.printf "map object count %i\n" object_count.contents

let increment_edge_count n =
  edge_count := !edge_count+1;
  Printf.printf "map object count %i\n" edge_count.contents

(*sets a point type*)
let init_point longitude latitude = 
  let new_point = new point in
  new_point#set_longitude longitude;
  new_point#set_latitude latitude;
  Printf.printf "successfully created a new point\n" 

(*goes through the xml file first to count the number of each instance of a object type*)
let xml_parser =
  let x = Xml.parse_file "MapMeObjects.xml" in
  Xml.iter (function
  Xml.Element ("myobject", attrs, _) ->
    List.iter (function ("description", desc) -> 
      if desc = "path" then
	let name = List.assoc "name" attrs in
	increment_path_count name
      else if desc = "mapObject" then
	let name = List.assoc "name" attrs in
        increment_mapObject_count name
      else if desc = "edge" then
        let name = List.assoc "name" attrs in
	increment_edge_count name
      else if desc = "point\n" then
          Printf.printf "this is a point"
      else Printf.printf "not a recognizable object\n" | _ -> ()) attrs
    | _ -> ()) x

(*arrays that store the objects*)

(*map objects*)
let dummyMapObject = new mapObject (*for initializing*)
let object_named_arr = Array.make object_count.contents "null" (*name array*)
let objArray = Array.make object_count.contents dummyMapObject (*stores the actual map object*) 

(*path objects*)
let dummyPathObject = new path
let path_named_arr = Array.make path_count.contents "null"
let pathArray = Array.make path_count.contents dummyPathObject

(*edge objects*)
let dummyEdgeObject = new edge
let edge_named_arr = Array.make edge_count.contents "null"
let edgeArray = Array.make edge_count.contents dummyEdgeObject

(*adds map object to the array*)
let add_mapObject name object_type point speed =
  let new_mapObject = new mapObject and
  p = split_str "," point in
  (*variables := IntMap.add 4 object_num.contents !variables;*)
  new_mapObject#set_name name;
  new_mapObject#set_objectType object_type;
  new_mapObject#set_speed speed;
  (*create a point type for the object*)
  let x = float_of_string(List.nth p 0) and 
  y = float_of_string(List.nth p 0) in 
  new_mapObject#set_point x y;
  objArray.(object_num.contents) <- new_mapObject;
  object_named_arr.(object_num.contents) <- name;
  object_num := !object_num+1;
  Printf.printf "added map object:%s to array\n" new_mapObject#get_name

(*adds path object to the array*)
let add_path name path_type number_of_points points =
  let new_path = new path in (*and 
  first_parse = split_str ";" points in
  let second_parse = split_str "," first_parse in*)
  new_path#set_name name;
  new_path#set_pathType path_type;
  new_path#set_numberOfPoints number_of_points;
  (*retrieve the list of points seperated by colons first*)
  (*Printf.printf "first list %s \n second list %s";*)
  pathArray.(path_num.contents) <- new_path;
  path_named_arr.(path_num.contents) <- name;
  path_num := !path_num+1;
  Printf.printf "added path object:%s to array\n" new_path#get_name

(*adds edge object to the array*)
let add_edge name weight path_1 path_2 =
  let new_edge = new edge in
  new_edge#set_name name;
  new_edge#set_weight weight;
  new_edge#set_path_one path_1;
  new_edge#set_path_two path_2;
  edgeArray.(edge_num.contents) <- new_edge;
  edge_named_arr.(edge_num.contents) <- name;
  edge_num := !edge_num+1;
  Printf.printf "added edge object:%s to array\n" new_edge#get_name

(*now that we know how many instances of each object is in the xml, we can go through the file again and add the object to the initialized array*)
let xml_parser_2 =
  let x = Xml.parse_file "MapMeObjects.xml" in
  Xml.iter (function
  Xml.Element ("myobject", attrs, _) ->
    List.iter (function ("description", desc) -> 
      if desc = "path" then
	let name = List.assoc "name" attrs and
            p_type = List.assoc "type" attrs and 
	    n_points = int_of_string(List.assoc "numOfPoints" attrs) and
	    points = List.assoc "points" attrs in
	add_path name p_type n_points points
      else if desc = "mapObject" then
	let name = List.assoc "name" attrs and
	    o_type = List.assoc "type" attrs and
	    point = List.assoc "point" attrs and
	    speed = int_of_string(List.assoc "speed" attrs) in
	add_mapObject name o_type point speed
      else if desc = "edge" then
	let name = List.assoc "name" attrs and
	    weight = float_of_string(List.assoc "weight" attrs) and
	    path_1 = List.assoc "path1" attrs and
	    path_2 = List.assoc "path2" attrs in
	add_edge name weight path_1 path_2
      else if desc = "point\n" then
          Printf.printf "this is a point"
      else Printf.printf "not a recognizable object\n" | _ -> ()) attrs
    | _ -> ()) x

(*below are methods used to find the index of the searched array *)
let find_index name array = 
  let rec loop i = 
    if i >= Array.length array then raise Not_found 
    else if array.(i) = name then i
    else loop(i+1) in 
loop 0;;
